package queue;

import java.util.Random;

/**
 * Created with IntelliJ IDEA.
 * Description:模拟实现阻塞队列
 * User: bjc
 * Date: 2025-08-26
 * Time: 19:58
 */
//这里简便实现，所以不使用泛型，默认String
class MyBlockingQueue {
    private String[] array = null;
    private int head = 0;//队头
    private int tail = 0;//队尾
    private int size = 0;//队列中元素个数


    //定义锁对象，实现线程安全
    private final Object locker = new Object();

    public MyBlockingQueue(int capacity) {
        array = new String[capacity];
    }

    //入队列
    public void put(String element) throws InterruptedException {
        //此处使用synchronized和在方法中使用效果一样，只不过方法中的锁对象是当前类对象
        synchronized (locker) {
            //判断队列是否满
            while (size == array.length) {
                //需要实现阻塞供功能
                locker.wait();
            }
            //新元素放到tail指向的位置
            array[tail] = element;
            //下述操作等价于：tail = (tail+1)%array.length;
            tail++;
            if (tail == array.length) {
                tail = 0;
            }
            size++;

            //入队列成功，则唤醒因为出队列阻塞的线程
            locker.notifyAll();
        }
    }

    //出队列
    public String take() throws InterruptedException {
        String element = null;
        synchronized (locker) {
            //判断队列是否为空
            while (size == 0) {
                //要进行阻塞
                locker.wait();
            }
            //获取元素
            element = array[head];
            head++;
            if (head == array.length) {
                head = 0;
            }
            size--;

            //出队列成功，则唤醒因为入队列阻塞的线程
            locker.notifyAll();

        }
        return element;
    }
}

public class QueueDemo2 {
    public static void main(String[] args) throws InterruptedException {
        /*MyBlockingQueue queue = new MyBlockingQueue(10);
        queue.put("aaa");
        queue.put("bbb");
        queue.put("ccc");
        queue.put("ddd");

        String elem = "";
        elem = queue.take();
        System.out.println("获取元素：" + elem);
        elem = queue.take();
        System.out.println("获取元素：" + elem);
        elem = queue.take();
        System.out.println("获取元素：" + elem);
        elem = queue.take();
        System.out.println("获取元素：" + elem);*/
        //使用上述的阻塞队列，实现生产者消者模型
        MyBlockingQueue queue = new MyBlockingQueue(10);
        Thread customer = new Thread(()->{
            while (true) {
                try {
                    String s = queue.take();
                    System.out.println("消费者获取：" + s);
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        },"消费者");
        customer.start();
        Thread producer = new Thread(()->{
            Random random = new Random();
            while (true){
                try {
                    String product = "产品" + random.nextInt(1000);
                    queue.put(product);
                    System.out.println("生产者生产：" + product);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
        },"生产者");
        producer.start();

        customer.join();
        producer.join();


    }
}
